// The Swift Programming Language
// https://docs.swift.org/swift-book

import Foundation
import LocalAuthentication


@available(macOS 12,*)
@available(iOS 15.0.0, *)
public actor AuthStatus: ObservableObject{
    public static var shared: AuthStatus = AuthStatus()
    
    @MainActor public var availableBiometryType: LABiometryType = .none{
        didSet{
            switch self.availableBiometryType {
            case .none:
                enableBiometryType = "None"
                
            case .touchID:
                enableBiometryType = "设备支持 Touch ID"
            case .faceID:
                enableBiometryType = "设备支持 Face ID"
            case .opticID:
                enableBiometryType = "不支持生物识别"
            default:
                enableBiometryType = "未知"
            }
        }
    }
    
    @MainActor
    @Published public var status: Status = .noPrivace
    
    @MainActor
    @Published public var enableBiometryType: String = "未知"
    
    @MainActor
    public func updateStatus(newStatus: Status){
        self.status = newStatus
        switch newStatus{
        case .evluateSuccess(let date):
            Task{
                await timeoutOperation()
            }
     break
        default:
            break

        }
       
        
    }
    @MainActor
    public func updateBiometryType(type: LABiometryType){
        self.availableBiometryType = type
        
    }
    @MainActor
    var timeoutSecond: UInt64 = 60
    @MainActor
    public func updateTimeoutSecond(timeout: UInt64){
        self.timeoutSecond = timeout
    }
    func timeoutOperation() async{
        try! await Task.sleep(nanoseconds: timeoutSecond * 1_000_000_000)
        await updateStatus(newStatus: .evluateTimeout)
    }
}

@available(macOS 12,*)
@available(iOS 15.0.0, *)
extension AuthStatus{
    public enum Status{
        case noPrivace
        case havePrivace
        
        case evluateSuccess(date: Date)
        case evluateTimeout
        case evluateFaild
        public var description: String{
            switch self {
            case .noPrivace:
                return "无权限"
            case .havePrivace:
                return "有权限"
            case .evluateSuccess(let date):
                return "验证成功 \(date.description)"
            
            case .evluateTimeout:
                return "验证已过期"
            case .evluateFaild:
                return "验证失败"
            }
        }
        
    }
}


@available(macOS 12,*)
@available(iOS 15.0.0, *)
@MainActor
public class RoAuth: ObservableObject{
    var context: LAContext = LAContext()
    var authStatus: AuthStatus = AuthStatus.shared
    var isEvalute: Bool = false
    var error: NSError? = nil
    
    public init(){
        let isAVailable = context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics,error: &error)
        if isAVailable{
            
            authStatus.updateStatus(newStatus: .havePrivace)
            authStatus.updateBiometryType(type: context.biometryType)
            self.isEvalute = true
            
        }
        else{
            
            authStatus.updateStatus(newStatus: .noPrivace)
            authStatus.updateBiometryType(type: context.biometryType)
           
        }
        
    }
    
    
    public func requestEvluate(timeout: UInt64 = 60){
        if !isEvalute{
            return
        }
        
        context.evaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, localizedReason: "检测用户身份") { success, error in
            if success{
                
                self.authStatus.updateStatus(newStatus: .evluateSuccess(date: Date.now))
                
                self.authStatus.updateTimeoutSecond(timeout: timeout)
                
            }else{
                self.authStatus.updateStatus(newStatus: .evluateFaild)
                
                
            }
        }
    }
}
